import React, {useEffect, useState} from 'react';
import {useHistory} from "react-router-dom";
import {useDispatch, useSelector} from "react-redux";
import Grid from "@material-ui/core/Grid";
import {Button, Step, StepContent, StepLabel, Stepper, Tooltip, Typography} from "@material-ui/core";
import Datasets from "./Dataset/Datasets";
import Filters from "./Filters/Filters";
import Analysis from "./Analysis/Analysis";
import ModalMessage from "../../Common/Modal/ModalMessage";
import {setLeftDrawerMenuIndex, skipBasicIndicatorTutorial} from "../../../../../redux/reducers/commonSettings";
import SnackbarMessage from "../../Common/Snackbar/SnackbarMessage";
import Visualize from "./Visualize/Visualize";
import ScrollToTop from "../../Common/ScrollTopWrapper/ScrollTopWrapper";
import {
  generateIndicatorPreview,
  getAllPlatforms,
  resetIndicatorSession,
  saveIndicatorPreview,
  setActiveIndicatorStep,
  setCompletedIndicatorStep,
  setGeneratedVisualizationCode
} from "../../../../../redux/reducers/editor";
import TutorialSlides from "../../Common/TutorialSlides/TutorialSlides";
import {editorTutorialSteps} from "../../../../../assets/constants/data/data";
import HistoryIcon from "@material-ui/icons/History";
import ArrowBackIcon from '@material-ui/icons/ArrowBack';
import {resetAllErrors} from "../../../../../redux/reducers/errorMessages";
import {scrollToTop} from "../../../../../assets/functions/functions";
import {makeStyles} from "@material-ui/core/styles";
import VisualizationPreview from "./VisualizationPreview/VisualizationPreview";
import {queryGeneratorWrapper, statementDurationWrapper} from "../../../../../ruleEngine/rulesGenerator";
import WbIncandescentIcon from "@material-ui/icons/WbIncandescent";

const useStyles = makeStyles(theme => ({
  gutterTop: {
    marginTop: theme.spacing(2)
  },
  gutterBottom: {
    marginBottom: theme.spacing(2)
  },
  stepper: {
    backgroundColor: theme.palette.type === 'light' ? theme.palette.common.white : "#212121"
  }
}))

export default function BasicIndicator(props) {
  // Props
  const {classes} = props;

  // Local constants from Redux store
  const activeStep = useSelector((state) => state.editor.common.activeStep);
  const completedStep = useSelector((state) => state.editor.common.completedStep);
  const openTutorial = useSelector((state) => state.commonSettings.basicIndicatorTutorialSkip);
  const selectedAnalysisMethod = useSelector(state => state.editor.selectedData.analysisMethod);
  const selectedVisualizationMethodsAndTypes = useSelector(state => state.editor.selectedData.visualizationMethodsAndTypes);
  const selectedVisualizationMapping = useSelector(state => state.editor.selectedData.mappingVizInputAnalysisOutput);
  const selectedPlatform = useSelector(state => state.editor.selectedData.platforms);
  const selectedActivityName = useSelector(state => state.editor.selectedData.activityName);
  const selectedActivityTypes = useSelector(state => state.editor.selectedData.activityTypes);
  const selectedActionOnActivities = useSelector(state => state.editor.selectedData.actionOnActivities);
  const selectedActivityExtensionData = useSelector(state => state.editor.selectedData.activityExtensionId);
  const selectedContextActivities = useSelector(state => state.editor.selectedData.contextActivities);
  const selectedResult = useSelector(state => state.editor.selectedData.result);
  const timeDurationData = useSelector(state => state.editor.selectedData.timeDuration);
  const selectedMappingAnalysisInputAttributesData = useSelector(state => state.editor.selectedData.mappingAnalysisInputAttributesData);
  const selectedAnalyticsMethodParams = useSelector(state => state.editor.selectedData.analysisMethodParams);


  // Local constants
  const history = useHistory();
  const dispatch = useDispatch();
  const styles = useStyles();
  const [feedback, setFeedback] = useState({
    showHelp: true,
    openMenu: true,
    openResetModal: false,
    openSaveProgressModal: false,
    openBackToEditorModal: false,
    openBackToDashboardModal: false,
    openSaveProgressErrorSnackbar: false,
  })

  useEffect(() => {
    scrollToTop();
  }, [])

  const handleFeedback = (name, value) => {
    setFeedback(() => ({
      ...feedback,
      [name]: !value,
    }))
  }

  const handleStepForward = () => {
    dispatch(setActiveIndicatorStep(activeStep + 1));
  }

  const handleStepBackward = () => {
    dispatch(setActiveIndicatorStep(activeStep - 1));
  }

  const handleComplete = () => {
    const newCompleted = completedStep;
    newCompleted[activeStep] = true;
    dispatch(setCompletedIndicatorStep(newCompleted));
  };

  const handleOpenTutorial = () => {
    dispatch(skipBasicIndicatorTutorial());
  }

  const handleSaveProgress = () => {
    handleFeedback("openSaveProgressModal", feedback.openSaveProgressModal);
  }

  const handleResetSession = () => {
    dispatch(resetIndicatorSession());
    dispatch(getAllPlatforms());
    dispatch(resetAllErrors());
    handleFeedback("openResetModal", feedback.openResetModal);
  }

  const handleBackToEditor = () => {
    history.push('/editor');
  }

  const handleBackToDashboard = () => {
    dispatch(setLeftDrawerMenuIndex(1));
    history.push('/dashboard');
  }

  const handleOpenVisualization = () => {
    dispatch(setGeneratedVisualizationCode("", ""))
    let queryBuilder = {
      platform: selectedPlatform,
      activityTypes: selectedActivityTypes,
      actionOnActivities: selectedActionOnActivities,
      activityName: selectedActivityName,
      result: selectedResult,
      contextActivities: selectedContextActivities,
      activityExtensionId: selectedActivityExtensionData
    };
    let parametersToBeReturnedInResult = {}
    selectedMappingAnalysisInputAttributesData.forEach(data => {
      parametersToBeReturnedInResult[data.outputPort.id] = 1
    })
    let methodInputParams = JSON.stringify(selectedAnalyticsMethodParams.reduce((obj, item) => {
      obj[item.id] = item.value.toString()
      return obj
    }, {}))
    let getIndicatorPreviewCode = {
      queries: {
        "0": {
          parametersToBeReturnedInResult: parametersToBeReturnedInResult,
          query: queryGeneratorWrapper(queryBuilder),
          statementDuration: statementDurationWrapper(timeDurationData)
        }
      },
      analyticsMethodId: {"0": selectedAnalysisMethod[0].id},
      queryToMethodConfig: {"0": {mapping: selectedMappingAnalysisInputAttributesData}},
      methodInputParams: {"0": methodInputParams},
      visualizationInputParams: {"0": ""},
      additionalParams: {width: 700, height: 600},
      visualizationLibraryId: selectedVisualizationMethodsAndTypes[0].id,
      visualizationTypeId: selectedVisualizationMethodsAndTypes[0].vId,
      methodToVisualizationConfig: {mapping: selectedVisualizationMapping}
    }
    // console.log(JSON.stringify(getIndicatorPreviewCode));
    dispatch(generateIndicatorPreview(getIndicatorPreviewCode));
    dispatch(saveIndicatorPreview(getIndicatorPreviewCode));

  }

  const steps = [
    {
      name: "Datasets",
      component: <Datasets handleStepForward={handleStepForward}/>
    },
    {
      name: "Filters",
      component: <Filters classes={classes}
                          handleStepForward={handleStepForward}
                          handleStepBackward={handleStepBackward}/>
    },
    {
      name: "Analysis Method",
      component: <Analysis classes={classes}
                           handleStepForward={handleStepForward}
                           handleStepBackward={handleStepBackward}/>
    },
    {
      name: "Visualization Method",
      component: <Visualize classes={classes}
                            handleOpenVisualization={handleOpenVisualization}
                            handleStepForward={handleStepForward}
                            handleStepBackward={handleStepBackward}
                            handleComplete={handleComplete}/>
    },
    {
      name: "Preview",
      component: <VisualizationPreview classes={classes} handleStepBackward={handleStepBackward}/>
    }];

  return (
    <>
      <Grid container direction="column" className={classes.root}>

        <Grid container justify="space-between" lg={9} className={styles.gutterBottom}>
          <Tooltip placement="down" title={"Go back to the GQI Editor"}>
            <Button onClick={() => history.push('/editor')} startIcon={<ArrowBackIcon/>}>
              Back
            </Button>
          </Tooltip>

          <Tooltip placement="down" title="All the selections done in the Basic indicator will be reset">
            <Button startIcon={<HistoryIcon/>} color="secondary" onClick={() =>
              handleFeedback("openResetModal", feedback.openResetModal)}>
              Reset
            </Button>
          </Tooltip>

        </Grid>

        <Typography variant="h3" className={styles.gutterBottom}> Basic Indicator </Typography>

        <Grid container justify="space-between" alignItems="center" lg={9}>

          <Grid item xs>
            <Typography variant='body1'>
              Choose dataset for your analysis, apply filters and analysis methods on the chosen dataset, and
              preview the visualization of the data.
            </Typography>
          </Grid>

          <Grid item>
            <Tooltip arrow placement="bottom" title="Open tutorial">
              <WbIncandescentIcon onClick={handleOpenTutorial} color="primary" style={{cursor: "pointer"}}/>
            </Tooltip>
          </Grid>

        </Grid>


        <Stepper activeStep={activeStep} orientation="vertical" className={styles.stepper}>
          {steps.map((step, index) => {
            return (
              <Step key={index}>
                <StepLabel>
                  <Typography variant="h5"> {step.name} </Typography>
                </StepLabel>
                <StepContent>
                  {step.component}
                </StepContent>
              </Step>
            )
          })}
        </Stepper>

      </Grid>

      <ScrollToTop/>

      <Grid item>
        <TutorialSlides
          state={openTutorial}
          handleOpen={handleOpenTutorial}
          tutorialSteps={editorTutorialSteps}/>
      </Grid>

      <ModalMessage
        dialogTitle={"You can continue editing from GQI Editor Indicator section!"}
        dialogPrimaryContext={`Your indicator progress is saved!`}
        openDialog={feedback.openBackToEditorModal}
        setOpenDialog={() => handleFeedback("openBackToEditorModal", feedback.openBackToEditorModal)}
        primaryAction={handleBackToEditor}
        primaryButton={"Back to GQI-Editor"}
        tertiaryAction={() => handleFeedback("openBackToEditorModal", feedback.openBackToEditorModal)}
        tertiaryButton={"Continue editing"}
      />

      <ModalMessage
        dialogTitle={"You can continue editing from GQI Editor Indicator section!"}
        dialogPrimaryContext={`Your indicator progress is saved!`}
        openDialog={feedback.openBackToDashboardModal}
        setOpenDialog={() => handleFeedback("openBackToDashboardModal", feedback.openBackToDashboardModal)}
        primaryAction={handleBackToDashboard}
        primaryButton={"To dashboard"}
        tertiaryAction={() => handleFeedback("openBackToDashboardModal", feedback.openBackToDashboardModal)}
        tertiaryButton={"Continue editing"}
      />

      <ModalMessage
        dialogTitle={"You are about to reset your progress!"}
        dialogPrimaryContext={`This will remove all your progress in the editor, 
        including your drafted Question, added indicators.\n Are you sure?`}
        openDialog={feedback.openResetModal}
        setOpenDialog={() => handleFeedback("openResetModal", feedback.openResetModal)}
        primaryAction={handleResetSession}
        primaryButton={"reset"}
        tertiaryAction={() => handleFeedback("openResetModal", feedback.openResetModal)}
        tertiaryButton={"cancel"}
      />

      <ModalMessage
        dialogTitle={"Your progress has been saved!"}
        dialogPrimaryContext={`All your progress in the editor is saved and
         can be found under "My Indicators".`}
        dialogSecondaryContext={`You can either "Continue Editing" or go "Back to Dashboard".`}
        openDialog={feedback.openSaveProgressModal}
        setOpenDialog={() => handleFeedback("openSaveProgressModal", feedback.openSaveProgressModal)}
        primaryAction={() => handleFeedback("openSaveProgressModal", feedback.openSaveProgressModal)}
        primaryButton={"continue editing"}
        tertiaryAction={handleBackToDashboard}
        tertiaryButton={"back to dashboard"}
      />

      <SnackbarMessage
        message={"You need to at least input an indicator name to save your progress!"}
        type={"error"}
        openSnackbar={feedback.openSaveProgressErrorSnackbar}
        setOpenSnackbar={() => handleFeedback("openSaveProgressErrorSnackbar", feedback.openSaveProgressErrorSnackbar)}
        duration={3000}
      />
    </>
  )
}
